#ifndef ROMS_MENU_H_
#define ROMS_MENU_H_

#include "std_lib_facilities.h"
//other types
#include "Category.h"
#include "Menu_Item.h"
#include "Recipe.h"
#include "Ingredient.h"
#include "Order.h"
#include "Order_Item.h"
#include "Point.h"
#include "Data_Table_Graph.h"
#include <map>

using namespace std;

namespace ROMS{   
	
	enum Msg_type{
	Exit_program=1, About_info, About_help, Close_about_box, Close_help_box,
	Read_recipes_ingredients, Read_orders, Read_category_menu_items,
	Show_order, Show_recipe, Show_menu, Show_categories, Show_order_items,
	Find_category_sales,Find_server_sales, Find_table_sales, Find_menu_item_sales, 
	Close_find_menu_item_sales, Find_item_sales_button,  			//added by EC for Part C
	Close_find_table_sales, Find_table_sales_button,				//added by NI, step C
	Close_find_server_sales,Find_server_sales_button,
	Update_add_order_item, Update_add_menu_item, Update_add_recipe,
	Update_add_category, Close_add_category, Add_category_button, 	//added by EC for Part C
	Close_add_order_item, Add_order_item_button,
	Close_add_menu_item,Add_menu_item_button,
	Tables_button, Orders_button, Categories_button, Recipes_button, Menu_items_button,
	Graph_total_sales,Close_graph,	// added by NI, step D
	Graph_table_sales, Close_table_graph,	//CZ Step D.2
  Graph_server_sales, Close_server_graph, //EC Part D3
	Display_window, Menu_bar_cb
	};
   
	struct InvalidType : std::runtime_error {
	  InvalidType(): runtime_error("Invalid type data") {}
	};

class ROMS_Menu {
public:
   struct InvalidData : std::runtime_error {
      InvalidData(): runtime_error("Invalid input data format") {}
   };

   struct InvalidFile : std::runtime_error {
      InvalidFile(): runtime_error("Invalid input file name") {}
   };

   enum Main_menu_options{ Info=1, Read, Show, Find, Update, Exit }; 

   enum Rec_type{ Cats=1, Menu_entry, Rec, Ingred, Ord, Ord_item };

   enum File_type{	Tbls=Tables_button, 
					CatMI=Categories_button, 
					Prds=Menu_items_button, 
					Carts=Orders_button, 
					Items=Recipes_button }; 
		
	ROMS_Menu();
   
   void display_main_menu() const;
   void display_info() const;//display assignment info & your name plus "Project Part I"
   void read();		 
   void update();
   void show() const;
   void find() const;
   void read_recipes_ingredients(string);
   void Read_orders(string);
   void read_catprds(string);
   
   /*************************
   Added by CZ for Part B.1 
   from EC previous code
   *************************/
   void write_recipes() const;
   void write_orders() const;
   void write_catmenu() const;
   /*************************
   End Addition by CZ for Part B.1
   *************************/
   	
   //show functions added to support GUI interface
   string show_button(Msg_type);

	template <typename T>
	string show_func(T t, string s)
	{
		string r;
		if(0==t.size())
			r = "No "+s+" Data Loaded\n";
		else
			for(int i=0; i<t.size(); ++i)
			{
				r+=t[i].display();
				r+="\n";
			}
		return r;
	}

	// added by NI -- B.3
	string show_improved_categories()
	{
		string str;
		if(categories.size() == 0)
		{
			str = "No Categories Data Loaded\n";
		}
		else
		{
			for(int i = 0;i < categories.size();i++)
			{
				str+=categories[i].display();
				str+="\n";
				for(int j = 0;j < menu_items.size();j++)
				{
					if(categories.at(i).get_cat_id() == menu_items.at(j).get_cat_id())
					{
						str+=" "+menu_items.at(j).get_name()+"\n";
					}
				}
				str+="\n";
			}
		}
		return str;
	}

	//added by NI B.3
	string show_improved_order_items()
	{
		string str;
		if(order_items.size() == 0)
		{
			str = "No Order Items Data Loaded\n";
		}
		else
		{
			for(int i = 0;i < order_items.size();i++)
			{
				str+=order_items[i].display();
				str+="\n";
				for(int j = 0;j < orders.size();j++)
				{
					if(order_items.at(i).get_order_id() == orders.at(j).get_order_id())
					{
						//str+=" "+orders.at(j).display();
						str+="ServerID: ";
						stringstream outServer;
						outServer << orders.at(j).get_server_id();
						str+= outServer.str();
						str+="\n";
						
						str+="TableID: ";
						stringstream outTable;
						outTable << orders.at(j).get_table_id();
						str+= outTable.str();
						str+="\n";

						str+="Date(YYYY/MM/DD) :";
						stringstream outYear,outMonth,outDay;
						outYear << orders.at(j).get_order_date().year();
						str+= outYear.str();
						str+="/";
						outMonth << orders.at(j).get_order_date().month();
						str+= outMonth.str();
						str+="/";
						outDay << orders.at(j).get_order_date().day();
						str+= outDay.str();
						str+="\n";

						str+="Time: ";
						stringstream outHour,outMinute;
						outHour << orders.at(j).get_order_time().get_hour();
						str+= outHour.str();
						str+=":";
						outMinute << orders.at(j).get_order_time().get_minute();
						str+= outMinute.str();
						str+="\n";
					}
				}
				str+="\n";
			}
		}
		return str;
	}
	
	double total_sales_table(int table_id); //added by NI step C
	string add_order_item(int order_id, int menu_item_id, int qty, string seat_id); //added by NI
	string get_frecipe()const{return frecipe;}//added by NI
    string get_forder()const{return forder;}//added by NI
    string get_fmenu()const{return fmenu;}//added by NI
	int maximum_sales(map<Point,double> sales);//added by NI step D
	map<Point,double> order_sales_by_month();//added by NI step D
	double total_menu_item_sales(int item_id); //EC Part C
	string add_category(int cat_id, string name); //EC Part C
   
   	double find_server_sales(int); //CZ Step C
	string add_menu_item(int, int, int, string, double, string); //CZ Step C
	
	vector<Data_Table_Graph> create_table_graph_data();	//CZ Step D
   
private:
   //private data
	vector<Category> categories;
	vector<Menu_Item> menu_items;
	vector<Recipe> recipes;
	vector<Ingredient> ingredients;
	vector<Order> orders;
	vector<Order_Item> order_items;

	int get_file_info(ifstream& ist, string prompt, string fname);	//A.1,2,3 merge added a function for common code
	void read_file(ifstream& file, int num_rec, Rec_type ftype);
	string get_long_string(ifstream& ist);
	string frecipe;//NI -- just ignore it
	string forder;//NI -- just ignore it
	string fmenu;//NI -- just ignore it
};
} //end namespace ROMS

#endif //ROMS_MENU_H_
